<?php

/**
 * 邮件发送器，单例模式
 * @author Hipop@126.com
 * @version 
 */
	
require_once 'Zend/Mail.php';
require_once 'Zend/Mail/Transport/Sendmail.php';
//require_once 'mimeparser/mime_parser.php';
//require_once 'library/Pear/Mail/mimeDecode.php';
require_once 'Pear/Mail/mimeDecode.php';
		
			

class Application_Service_Mail
{
	
	/**
	 * 邮件发送器
	 * @var Zend_Mail
	 */
	private $_mailSender;
	
	/**
	 * 邮件阅读器(从本地或远程读取邮件)
	 * @var Zend_Mail_Storage_Pop3 | Zend_Mail_Storage_IMAP
	 */
	private $_mailReader;
	
	/**
	 * 本类的静态单例
	 * @var Application_Service_Mail
	 */
	private static $_instance;
	
	/**
	 * 邮件存储地址
	 * @var string
	 */
	protected static $_mailFileDir = '/mail';
	
	/**
	 * @var array
	 */
	private  $appconf;
	
	/**
	 * 邮件收发器
	 */
	private function __construct($charset = "UTF8")
	{
		$this->appconf = new Zend_Session_Namespace(Bootstrap::APP_CONF_SESSION_KEY);		
		self::$_mailFileDir = $this->appconf->mailPath;
		$this->_mailReader = new Zend_Mail_Storage();
	}
	
	private function __clone(){}
	
	
	/**
	 * 获取单例
	 * @param string $charset
	 * @return Application_Service_Mail
	 */
	public static function getInstance($charset = "UTF8")
	{
		if( !(self::$_instance instanceof  self )){
			self::$_instance = new self($charset);
		}
		return self::$_instance;
	}
	
	/**
	 * 设置发件器参数
	 * @param array|string|int $email 参数 或email地址或email账户id
	 * @return void
	 */
	public function setSenderConf($conf)
	{
		$mailconf = $conf;
		
		$mailconf["name"] 	= $mailconf["smtp"];
		$mailconf["port"] 	= $mailconf["smtp_port"];
		$mailconf["auth"]   = $mailconf["smtp_author"];
		
		$transport = new Zend_Mail_Transport_Smtp($mailconf["name"],$mailconf);
		$this->_mailSender = new Zend_Mail($mailconf["charset"]);
		$this->_mailSender->setDefaultTransport($transport);
		
		//设置默认的发件人账户和名称
		$this->_mailSender->setDefaultFrom($mailconf['email'], $mailconf['showname']);
		$this->_mailSender->setDefaultReplyTo($mailconf['email'], $mailconf['showname']);
	}	
	
	/**
	 * 发送邮件
	 * @param array $email //邮件
	 * @return Zend_Mail Provides fluent interface
	 */
	public function sendMail($email)
	{
		//多个联系人，用半角分号分开
		$recipients = explode(";", $email["to"]);		
		$this->_mailSender->clearRecipients()->addTo($recipients) 	 //设置收信人
			 ->clearSubject()->setSubject($email['subject']) 		 //设置主题
			 ->setBodyHtml($email['mail'], "UTF-8"); //设置BODY
		
		//attachment
		if(!empty($email->attachment)){
			$filePath = $this->appconf->uploadPath . $email->attachment;
			if(file_exists($filePath)){
				//$attachmentB64 = base64_encode(file_get_contents($filePath));
				$at = $this->_mailSender->createAttachment(file_get_contents($filePath));
				$at->type        = $email->attachment_mime;
				//$at->disposition = Zend_Mime::DISPOSITION_INLINE;
				//$at->encoding    = Zend_Mime::ENCODING_BASE64;
				$at->filename    = $email->attachment_name;				
			}
		}	
		return $this->_mailSender->send();
	}
	
	/**
	 * 设置邮件阅读器
	 * @param array $conf
	 */
	public function setReadConf($conf)
	{		
		//传递给存储器的参数
		$readerConf = array(
			"user" 		=> $conf["username"],
			"password" 	=> $conf["password"]
		);		
		if(!empty($conf["secure"])){
			$readerConf["ssl"] = $conf["secure"];
		}
		
		//传递的接收协议
		$protocol = strtoupper($conf["reader"]);
		if($protocol == "POP3"){
			$readerConf["host"] = $conf["pop3"];
			$readerConf["port"] = $conf["pop3_port"];			
			$this->_mailReader = new Zend_Mail_Storage_Pop3($readerConf);
		}elseif ($protocol == "IMAP"){
			$readerConf["host"] = $conf["imap"];
			$readerConf["port"] = $conf["imap_port"];			
			$this->_mailReader = new Zend_Mail_Storage_Imap($readerConf);
			//$this->_mailReader->setFlags();
		}
	}
	
	/**
	 * 读取邮件内容
	 * @param string $path
	 * @return array | null
	 */
	public static function viewMail($path)
	{
		//$input = "=?GBK?B?vqm2q834yc/JzLPHy8279czh0NGjusT6tqm1pQ==?=\n =?GBK?B?1tC1xMnMxrfS0cvNs/ajrMfr1/a6w8rVu/XXvLG4?=";
		//var_dump($input);
		//$input = preg_replace('/\?=(\s)+=\?[^?]+\?(q|b)\?/i', '', $input);
		//var_dump($input);
		//preg_match('/(=\?([^?]+)\?(q|b)\?([^?]*)\?=)/i', $input, $matches);
		//echo base64_decode($matches[4]) ,"\n";
		//echo base64_encode(iconv("UTF-8", "GBK", "京东网上商城送货提醒：您订单中的商品已送出，请做好收货准备"));
		
		//print_r($matches);die();
		
		$mimeDecode = new Mail_mimeDecode(file_get_contents($path));
		$mailDecode = $mimeDecode->decode(array(
				"include_bodies" => TRUE,
				"decode_bodies"	 => TRUE,
				"decode_headers" => TRUE,
				"charset"		 => "UTF-8"
			)
		);
		
		//头数据
		$headerDecode = $mailDecode->headers;		
		//统一转成U8码				
		$headerDecode = Mail_mimeDecode::iconvHeaders($headerDecode,"UTF-8");	
		
		//body数据
		$bodyDecode   = "";//$headerDecode;
				
		if(!empty($mailDecode->body)){
			//如果直接解析为body
			$bodyDecode = $mailDecode->body;
			if (!empty($mailDecode->ctype_parameters["charset"])){
				$bodyDecode = iconv($mailDecode->ctype_parameters["charset"], "UTF-8", $bodyDecode);
			}
		} elseif (!empty($mailDecode->parts)){
			//如果邮件包含多个部分
			$parts = $mailDecode->parts;
			$bodyDecode = Mail_mimeDecode::iconvTextBody($mailDecode->parts,"UTF-8");
		}
		//($mailDecode);
		
		//附件
		$attachment = array();
		//print_r($mailDecode);die();
		Mail_mimeDecode::getAttachemtSummary($mailDecode->parts, $attachment);
		//print_r($attachment);die();
		$mailDecode = $headerDecode;
		$mailDecode["body"] = preg_replace("/(<script .+ <\/script>)|(<META.+>)/i","",$bodyDecode);
		$mailDecode["attachment"] = $attachment;
		//print_r($mailDecode);die();
		return $mailDecode;
	}
	
	/**
	 * 下载附件
	 * @param string $path
	 * @return array | null
	 */
	public function downloadAttachment($path,$partid=0)
	{
		$mimeDecode = new Mail_mimeDecode(file_get_contents($path));
		$mailDecode = $mimeDecode->decode(array(
				"include_bodies" => TRUE,
				"decode_bodies"	 => TRUE,
				"decode_headers" => TRUE,
				"charset"		 => "UTF-8"
			)
		);		

		//body数据
		$bodyDecode   = "";//$headerDecode;
				
		if (!empty($mailDecode->parts)){
			//如果邮件包含多个部分
			$parts = $mailDecode->parts;
			$bodyDecode = Mail_mimeDecode::downloadAttachemt($mailDecode->parts,$partid);
		}else {
			return FALSE;
		}
	}
	
	/**
	 * 收件，这是个费时的工作，会启动极限超时机制
	 */
	public function reciveMail()
	{
		$id = 1;
		$mailInboxM = new Application_Model_DbTable_Mailinbox();
		$customerM	= new Application_Model_DbTable_Customer();
		$custagentM = new Application_Model_DbTable_Custagent();
		
		for($id = count($this->_mailReader);--$id;){
			echo $id , "\n";
			
			//邮件数据			
			$mailRawHeader  = $this->_mailReader->getRawHeader($id);
			
			//邮件解码器
			$mimeDecode 	= new Mail_mimeDecode($mailRawHeader);
			
			//邮件头解码
			$mailDecode 	= $mimeDecode->decode(array(
									"include_bodies" => FALSE,
									"decode_bodies"	 => FALSE,
									"decode_headers" => TRUE,
									"charset" 		 => "UTF-8"
								)); 

			//解码后的头信息
			$mailDecHeader = $mailDecode->headers;
					
			if($mailDecHeader){
			
				//邮件唯一标志
				$mailID = "";
				if(empty($mailDecHeader["message-id"])){
					$mailID = md5(implode(',', $mailDecHeader));
				}else{
					$mailID = str_replace(array("<",">","\\","/",":","*","?","|"),'', $mailDecHeader["message-id"]);
				}
				
				//邮件发送日期
				$mailTime = time();
				if(empty($mailDecHeader["date"])){
					
				}else{
					$mailTime = strtotime($mailDecHeader["date"]);
				}
				$mailDate = date("Y-m-d",$mailTime);
							
				//邮件存储位置
				$mailDir = self::$_mailFileDir . "{$mailDate}/{$mailID}.eml";
				
				//存储邮件文件
				if(!file_exists($mailDir)){
					//收取并保存
					$pathinfo = pathinfo($mailDir);
					if(!is_dir($pathinfo["dirname"]))
						@mkdir($pathinfo["dirname"]);
					//$mailRawBody = $mail->getContent();
					$mailRawContent = $mailRawHeader . $this->_mailReader->getRawContent($id); //有内存风险
					file_put_contents($mailDir,$mailRawContent,FILE_APPEND);
				}
				
				//要插入数据库的信息	
				$data = array();
				
				$data["send_time"]	= $mailTime;
				
				/*$test = "DNSPod <domain.expired2@dnspod.cn>?*@#$%$^&\\//:n'";
				preg_match("/^(.*)<(.+)>.*$/s", $test,$from);
				print_r($from);die();*/
				
				preg_match("/^(.*)<(.+)>.*$/s", $mailDecHeader["from"],$from);
				$data["from"] 		= empty($from[2])?$mailDecHeader["from"]:$from[2];
				$data["from_name"]  = $from[1];
							
				preg_match("/^(.*)<(.+)>.*$/s", $mailDecHeader["to"],$to);
				$data["to"] 		= empty($to[2])?$mailDecHeader["to"]:$to[2];
				$data["to_name"]  	= $to[1];
				
				preg_match("/^(.*)<(.+)>.*$/s", $mailDecHeader["reply_to"],$reply_to);
				$data["reply_to"] 		= $reply_to[2];
				//$data["reply_to_name"]  = $reply_to[1];
				
				$data["subject"] 	= $mailDecHeader["subject"];
				
			
				//if($id > 100)die();
			
			
				//判断是否已经记录在案
				$exists = $mailInboxM->fetchRow(" `mailid` = '$mailID' ");
				if($exists){
					//跳过
					//continue;
					//退出循环
					break;
				}else{
					//写入数据库
					if($customer = $customerM->getItemByMail($data["from"])){
						$customer = $customer->id;
					}elseif ($customer = $custagentM->getCustomerByMail($data["from"])){
						$customer = $customer->id;
					};
					if(!empty($customer)){
						$data["customer"] = $customer;
					}

					$data = array_merge($data,array(
						"mailid" => $mailID,
						"maildir" => str_replace(APPLICATION_PATH."/..", "", self::$_mailFileDir . "{$mailDate}/{$mailID}.eml"),
						//"mailheader" => mb_convert_encoding($mailRawHeader, 'UTF-8'),
						"create_time" => time()
					));
					try{
						$mailInboxM->insert($data);
					}catch (Exception $e){
						Application_Service_Msg::write(
							"有一封邮件收取异常，发信人：{$data["from_name"]}<{$data["from"]}>;发送时间：{$mailDate}。请联系提供商提取邮件！
							runtime error : {$e->getMessage()}
							",
							Application_Model_Msg::TYPE_SYS_LOG,
							Application_Model_Msg::FROM_SYS,
							Application_Model_Msg::TO_ADMIN
						);
					}
				}
			}else {
				//转码失败
				Application_Service_Msg::write(
					"有一封邮件转码失败。请联系提供商提取邮件！",
					Application_Model_Msg::TYPE_SYS_LOG,
					Application_Model_Msg::FROM_SYS,
					Application_Model_Msg::TO_ADMIN
				);
			}
			
			//标记置位
			$mimeDecode = $id;
		}
	}
}